package admin

import (
	"ecms/models"
	"ecms/utils/reflects"
	"ecms/utils/repository"
	"ecms/utils/response"
	"ecms/utils/tools"
	"ecms/utils/validator"
	"github.com/gin-gonic/gin"
	"time"
)

type PermissionController struct {
}

// Menus 菜单列表
func (c *PermissionController) Menus(ctx *gin.Context) {
	permissions := make([]models.AdminPermission, 0)
	repo := repository.New(&models.AdminPermission{})
	if !repo.SelectAll("sort DESC", &permissions, "status = ? AND is_menu = ? AND is_deleted = ?", 1, 1, 0) {
		response.FailJson(ctx, "查询失败, 请稍后再试", nil)
		return
	}

	type treeAbleMenu struct {
		Name        string `json:"name"`
		Icon        string `json:"icon"`
		Identify    string `json:"identify"`
		Description string `json:"description"`
		tools.TreeAbleImplInt64
	}

	treeAbleMenus := make([]tools.TreeAble, 0)
	for _, v := range permissions {
		treeAbleMenus = append(treeAbleMenus, &treeAbleMenu{
			Name:        v.Name,
			Icon:        v.Icon,
			Identify:    v.Identify,
			Description: v.Description,
			TreeAbleImplInt64: tools.TreeAbleImplInt64{
				Id:       v.Id,
				Pid:      v.Pid,
				Children: make([]tools.TreeAble, 0),
			},
		})
	}

	response.SuccessJson(ctx, "查询成功", tools.TreeData(treeAbleMenus, 0))
}

// Index 权限列表
func (c *PermissionController) Index(ctx *gin.Context) {
	permissions := make([]models.AdminPermission, 0)
	repo := repository.New(&models.AdminPermission{})
	if !repo.SelectAll("sort ASC, updated_at DESC", &permissions, "status = ? AND is_deleted = ?", 1, 0) {
		response.FailJson(ctx, "查询失败, 请稍后再试", nil)
		return
	}

	type treeAblePermission struct {
		Name        string `gorm:"name" json:"name"`               // 权限名称
		Icon        string `gorm:"icon" json:"icon"`               // 图标
		Description string `gorm:"description" json:"description"` // 权限简介
		Tooltip     string `gorm:"tooltip" json:"tooltip"`         // 权限的完整说明
		Identify    string `gorm:"identify" json:"identify"`       // 权限标识码
		Sort        int64  `gorm:"sort" json:"sort"`               // 排序
		IsMenu      int64  `gorm:"is_menu" json:"is_menu"`         // 是否是菜单
		tools.TreeAbleImplInt64
	}

	treeAblePermissions := make([]tools.TreeAble, 0)
	for _, v := range permissions {
		treeAblePermissions = append(treeAblePermissions, &treeAblePermission{
			Name:        v.Name,
			Icon:        v.Icon,
			Description: v.Description,
			Tooltip:     v.Tooltip,
			Identify:    v.Identify,
			Sort:        v.Sort,
			IsMenu:      v.IsMenu,
			TreeAbleImplInt64: tools.TreeAbleImplInt64{
				Id:       v.Id,
				Pid:      v.Pid,
				Children: make([]tools.TreeAble, 0),
			},
		})
	}

	response.SuccessJson(ctx, "查询成功", tools.TreeData(treeAblePermissions, 0))
}

// Create 权限添加
func (c *PermissionController) Create(ctx *gin.Context) {
	reqData := &models.AdminPermission{
		Status:    1,
		IsDeleted: 0,
		CreatedAt: response.Time(time.Now().Local()),
		UpdatedAt: response.Time(time.Now().Local()),
	}
	rules := validator.NewRules(
		validator.NewRule("name", "权限名称", true, validator.TypeNoEmpty),
		validator.NewRule("icon", "权限图标", true, validator.TypeAlphaDash),
		validator.NewRule("description", "权限简介", false, validator.TypeNoEmpty),
		validator.NewRule("tooltip", "详细说明", false, validator.TypeNoEmpty),
		validator.NewRule("identify", "权限标识", true, validator.TypeLink),
		validator.NewRule("pid", "父级权限", true, validator.TypeNumber),
		validator.NewRule("sort", "排序", true, validator.TypeNumber),
		validator.NewRule("is_menu", "菜单显示", true, validator.TypeNumber),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	// 检查同级是否存在同名权限
	hasSame := &models.AdminPermission{}
	repo := repository.New(&models.AdminPermission{})
	if repo.Find(hasSame, "is_deleted = 0 AND pid = ? AND (name = ? OR identify = ?)", reqData.Pid, reqData.Name, reqData.Identify) && hasSame.Id != 0 {
		response.FailJson(ctx, "同级下已存在同名权限", nil)
		return
	}

	// 创建
	if !repo.Create(reqData) {
		response.FailJson(ctx, "添加失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "添加成功", nil)
}

// Update 权限更新
func (c *PermissionController) Update(ctx *gin.Context) {
	reqData := &models.AdminPermission{}
	rules := validator.NewRules(
		validator.NewRule("id", "权限ID", true, validator.TypeNumberNoneZero),
		validator.NewRule("name", "权限名称", true, validator.TypeNoEmpty),
		validator.NewRule("icon", "权限图标", true, validator.TypeAlphaDash),
		validator.NewRule("description", "权限简介", false, validator.TypeNoEmpty),
		validator.NewRule("tooltip", "详细说明", false, validator.TypeNoEmpty),
		validator.NewRule("identify", "权限标识", true, validator.TypeLink),
		validator.NewRule("pid", "父级权限", true, validator.TypeNumber),
		validator.NewRule("sort", "排序", true, validator.TypeNumber),
		validator.NewRule("is_menu", "菜单显示", true, validator.TypeNumber),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	// 检查同级是否存在同名权限
	hasSame := &models.AdminPermission{}
	repo := repository.New(&models.AdminPermission{})
	if repo.Find(hasSame, "is_deleted = 0 AND pid = ? AND (name = ? OR identify = ?) AND id <> ?", reqData.Pid, reqData.Name, reqData.Identify, reqData.Id) && hasSame.Id != 0 {
		response.FailJson(ctx, "同级下已存在同名权限", nil)
		return
	}

	// 权限是否存在
	hasPerm := &models.AdminPermission{}
	if !repo.FindById(reqData.Id, hasPerm) || hasPerm.Id == 0 {
		response.FailJson(ctx, "权限信息已失效", nil)
		return
	}

	// 更新字段值
	refObj, err := reflects.NewObject(hasPerm)
	if err != nil {
		response.FailJson(ctx, "编辑失败, 请稍后再试", nil)
		return
	}
	fields := []string{"name", "icon", "description", "tooltip", "identify", "pid", "sort", "is_menu"}
	refObj.BatchSetValueFromFields(fields, reqData)
	hasPerm.UpdatedAt = response.Time(time.Now().Local())

	if !repo.UpdateById(hasPerm.Id, hasPerm) {
		response.FailJson(ctx, "编辑失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "编辑成功", nil)
}

// Delete 权限删除接口
func (c *PermissionController) Delete(ctx *gin.Context) {
	reqData := &models.AdminPermission{}
	rules := validator.NewRules(
		validator.NewRule("id", "权限ID", true, validator.TypeNumberNoneZero),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	hasPerm := &models.AdminPermission{}
	repo := repository.New(&models.AdminPermission{})
	if !repo.Find(hasPerm, "is_deleted = 0 AND id = ?", reqData.Id) || hasPerm.Id == 0 {
		response.FailJson(ctx, "权限信息已失效", nil)
		return
	}

	if !repo.DeleteById(reqData.Id) {
		response.FailJson(ctx, "删除失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "删除成功", nil)
}
